﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Media.Imaging;
using System.Text;
using System.IO;
using System.IO.IsolatedStorage;

namespace TAXILISM
{
    public class FBPhotoPost
    {
        #region class setup

        //local property variables

        private string ms_boundary = string.Empty;
        private string ms_accesstoken = string.Empty;
        private BitmapImage mimg_phototopost;
        private string ms_caption = "WP7 Upload Photo";

        private const string Prefix = "--";
        private const string NewLine = "\r\n";

        public FBPhotoPost() { }

        public BitmapImage PhotoToPost
        {
            get { return mimg_phototopost; }
            set { mimg_phototopost = value; 
            }
        }

        public string PhotoCaption
        {
            get { return ms_caption; }
            set { ms_caption = value; }
        }

        public String BoundaryString
        {
            get
            {
                if (ms_boundary == string.Empty)
                { ResetBoundaryString(); }
                return ms_boundary;
            }
        }

        public void ResetBoundaryString()
        {
            ms_boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");
        }

        public String AccessToken
        {
            get
            { return ms_accesstoken; }
            set
            { ms_accesstoken = value; }
        }

        #endregion

        #region Post Data Stuff

        public void PostPhoto()
        {
            if ((mimg_phototopost != null) && (ms_accesstoken != String.Empty))
                PostPhotoHTTPWebRequest(BuildPostData());
        }

        private byte[] BuildPostData()
        //Uses the PhotoToPost and BoundaryString to build a byte array we can use as the data in the POST message 
        {
            // Build up the post message header
            var sb = new StringBuilder();
            //accepts a message parameter which will be the caption to go with the photo
            sb.Append(Prefix).Append(BoundaryString).Append(NewLine);
            sb.Append("Content-Disposition: form-data; name=\"message\"");
            sb.Append(NewLine);
            sb.Append(NewLine);
            sb.Append(PhotoCaption);
            sb.Append(NewLine);

            string filename = @"FacebookUpload.jpg";
            string contenttype = @"image/jpeg";

            sb.Append(Prefix).Append(BoundaryString).Append(NewLine);
            sb.Append("Content-Disposition: form-data; filename=\"").Append(filename).Append("\"").Append(NewLine);
            sb.Append("Content-Type: ").Append(contenttype).Append(NewLine).Append(NewLine);

            byte[] ba_Header = Encoding.UTF8.GetBytes(sb.ToString());
            byte[] ba_photo = ImageToByteArray(PhotoToPost);
            byte[] ba_footer = Encoding.UTF8.GetBytes(String.Concat(NewLine, Prefix, BoundaryString, Prefix, NewLine));

            byte[] postData = new byte[ba_Header.Length + ba_photo.Length + ba_footer.Length];
            Buffer.BlockCopy(ba_Header, 0, postData, 0, ba_Header.Length);
            Buffer.BlockCopy(ba_photo, 0, postData, ba_Header.Length, ba_photo.Length);
            Buffer.BlockCopy(ba_footer, 0, postData, ba_Header.Length + ba_photo.Length, ba_footer.Length);

            ms_lastposteddata = ByteArrayToString(postData);

            return postData;
        }

        private string ByteArrayToString(byte[] bytes)
        {
            System.Text.Encoding enc = System.Text.Encoding.UTF8;
            string PostString = enc.GetString(bytes, 0, bytes.Length);
            return PostString;
        }

        private string ms_lastposteddata = "No Data Posted Yet";

        public string LastPostedData
        {
            get { return ms_lastposteddata; }
        }

        #endregion

        #region HTTPWebRequest

        //Posts the data to Facebook - can only post to me/photos (no access to users wall)
        private void PostPhotoHTTPWebRequest(byte[] postData)
        {
            try
            {
                HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(string.Format("https://graph.facebook.com/me/photos?access_token={0}", App.AccessToken));
                httpWebRequest.ContentType = String.Concat("multipart/form-data; boundary=", BoundaryString);
                httpWebRequest.Method = "POST";
                // start the asynchronous operation
                httpWebRequest.BeginGetRequestStream((ar) => { GetRequestStreamCallback(ar, postData); }, httpWebRequest);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void GetRequestStreamCallback(IAsyncResult asynchronousResult, byte[] postData)
        {
            try
            {
                HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
                // End the operation
                Stream postStream = request.EndGetRequestStream(asynchronousResult);

                postStream.Write(postData, 0, postData.Length);
                postStream.Close();

                request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
            }
            catch (Exception ex)
            {
                Deployment.Current.Dispatcher.BeginInvoke(() => { UpdatePostStatus("Error Uploading [GetRequestStreamCallback]:", ex.ToString()); });
            }
        }

        private void GetResponseCallback(IAsyncResult asynchronousResult)
        {
            try
            {
                HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
                HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
                Stream streamResponse = response.GetResponseStream();
                StreamReader streamRead = new StreamReader(streamResponse);
                string responseString = streamRead.ReadToEnd();
                System.Diagnostics.Debug.WriteLine(responseString);

                Deployment.Current.Dispatcher.BeginInvoke(() => { UpdatePostStatus("Upload Success! Picture ID:", responseString); });

                streamResponse.Close();
                streamRead.Close();
                response.Close();
            }
            catch (Exception ex)
            {
                Deployment.Current.Dispatcher.BeginInvoke(() => { UpdatePostStatus("Error Uploading [GetResponseCallback]:", ex.ToString()); });
            }
        }

        #endregion

        #region ImageManipulation

        public BitmapImage GetImageFromIsolatedStorage(String ImageFileName)
        {
            {
                using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    using (IsolatedStorageFileStream isfs = isf.OpenFile(ImageFileName, FileMode.Open, FileAccess.Read))
                    {
                        BitmapImage bmpimg = new BitmapImage();
                        bmpimg.SetSource(isfs);
                        isfs.Close();
                        return bmpimg;
                    }
                }
            }
        }

        private byte[] ImageToByteArray(BitmapImage bm_Image)
        {
            byte[] data;
            using (MemoryStream stream = new MemoryStream()) 
            {
                WriteableBitmap wBitmap = new WriteableBitmap(bm_Image.PixelWidth, bm_Image.PixelHeight);
                wBitmap.SaveJpeg(stream, wBitmap.PixelWidth, wBitmap.PixelHeight, 0, 100);
                stream.Seek(0, SeekOrigin.Begin);
                data = stream.GetBuffer();
            }
            return data;
            //byte[] data;
            //{
            //    MemoryStream ms_Image = new MemoryStream();
            //    bm_Image.Save
            //    System.Windows.Media.Imaging.Extensions.SaveJpeg(new WriteableBitmap(bm_Image), ms_Image, bm_Image.PixelWidth, bm_Image.PixelHeight, 0, 100);

            //    ms_Image.Seek(0, 0);
            //    data = new byte[ms_Image.Length];
            //    ms_Image.Read(data, 0, data.Length);
            //    ms_Image.Close();
            //}

            //return data;
        }

        public BitmapImage GetBitmapImageFromUIElement(UIElement element)

        //GetBitmapImageFromUIElement accepts a UIElement (canvas, grid, image, etc...)

        //and builds a BitmapImage of it including any child elements
        {
            try
            {
                


                WriteableBitmap bmp = new WriteableBitmap(element,null);
                //try
                //{
                //    bmp.Render(element, null);
                //    bmp.Invalidate();
                //}
                //catch (Exception ex)
                //{
                //    MessageBox.Show(ex.ToString());
                //}

                MemoryStream ms_Image = new MemoryStream();
                
                bmp.SaveJpeg(ms_Image, (int)bmp.PixelWidth, (int)bmp.PixelHeight, 0, 100);
                ms_Image.Seek(0, 0);
                BitmapImage bmpimg = new BitmapImage();
                bmpimg.SetSource(ms_Image);
                ms_Image.Close();
                return bmpimg;
                
            }
            catch (Exception ex)
            {
                UpdatePostStatus("Error Getting Bitmap from UIElement:", ex.Message);
                return null;
            }
        }

        #endregion

        #region Events code

        private void UpdatePostStatus(string strHeader, string strContents)
        {
            if (PostStatus != null)
            {
                PostStatus(this, new PostStatusEventArgs(strHeader, strContents));
            }
        }

        public class PostStatusEventArgs : EventArgs
        {
            private readonly string msg_header = string.Empty;
            private readonly string msg_contents = string.Empty;
            // Constructor.
            public PostStatusEventArgs(string msgHeader, string msgContents)
            {
                this.msg_header = msgHeader;
                this.msg_contents = msgContents;
            }

            public string MessageHeader { get { return msg_header; } }
            public string MessageContents { get { return msg_contents; } }
        }


        public delegate void PostStatusEventHandler(object sender,PostStatusEventArgs e);

        public event PostStatusEventHandler PostStatus;

        #endregion 

    }
}
